/*
 * @(#)RuleBaseObjectDAObject.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.rules.dao;

import java.io.File;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mandarax.kernel.ClauseSet;
import org.mandarax.kernel.InferenceException;
import org.mandarax.kernel.KnowledgeBase;
import org.mandarax.kernel.Query;
import org.mandarax.kernel.ResultSet;
import org.mandarax.kernel.Rule;
import org.mandarax.reference.AdvancedKnowledgeBase;
import org.mandarax.reference.ResolutionInferenceEngine4;
import org.mandarax.zkb.ZKBException;
import org.mandarax.zkb.ZKBManager;
import org.mandarax.zkb.framework.ZKBDriver_2_0;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.bean.AbstractBaseObject;
import com.dcivision.framework.bean.BeansSorter;
import com.dcivision.framework.dao.AbstractDAObject;
import com.dcivision.framework.web.AbstractSearchForm;
import com.dcivision.rules.RuleErrorConstant;
import com.dcivision.rules.RuleOperationConstant;
import com.dcivision.rules.bean.RuleBaseObject;
import com.dcivision.rules.core.RuleMemberFactory;
import com.dcivision.rules.core.XMLSerializationReadOPS;

/**
 * <p>Class Name:      RuleBaseObjectDAObject.java </p>
 * <p>Description:     This class is the data access bean for a KnowledgeBase file. </p>
 *
 * @author         Tony Chen
 * @company        DCIVision Limited
 * @creation date  25/7/2005
 * @version        $Revision: 1.18 $
 */
public class RuleBaseObjectDAObject extends AbstractDAObject {

  protected Log              log            = LogFactory.getLog(this.getClass().getName());

  public static final String TABLE_NAME     = "RULE_ENGINE";

  private String             RULE_FILE_NAME = null;

  //private  RuleManager ruleManager = new RuleManager();

  /**
   * init the rule file name
   * @param ruleFileName
   */
  public void initRuleFileName(String ruleFileName) {
    this.RULE_FILE_NAME = ruleFileName;
    log.debug("ruleFileName: " + ruleFileName);
  }

  public RuleBaseObjectDAObject(SessionContainer sessionContainer, Connection dbConn) {
    super(sessionContainer, dbConn);
  }

  protected void initDBSetting() {
    this.baseTableName = TABLE_NAME;
  }

  protected synchronized AbstractBaseObject getByID(Integer id) throws ApplicationException {
    return this.getRuleBaseObjectByRuleID(RULE_FILE_NAME, id);
  }

  /**
   * get a RuleBaseObject list by the search form
   * @param searchForm a Abstract Search Form
   * @return list
   */
  protected synchronized List getList(AbstractSearchForm searchForm) throws ApplicationException {
    List result = new ArrayList();
    log.debug("============== get list =============");
    result = this.getRuleList(this.RULE_FILE_NAME, searchForm);
    return result;
  }

  /**
   * get all RuleBaseObjects 
   * 
   * @return AbstractBaseObject
   */
  protected synchronized List getList() throws ApplicationException {
    List result = new ArrayList();
    result = this.getAllRuleList(this.RULE_FILE_NAME);
    return result;
  }

  protected void validateInsert(AbstractBaseObject obj) throws ApplicationException {
    RuleBaseObject ruleObject = (RuleBaseObject) obj;
    try {
      Object object = this.getRuleBaseObjectByRuleName(this.RULE_FILE_NAME, ruleObject.getRuleName());
      if (!Utility.isEmpty(object)) {
        throw new ApplicationException(RuleErrorConstant.RULE_DUPLICATE_RULE_NAME);
      }
    } catch (ApplicationException appEx) {
      if (!RuleErrorConstant.RULE_RULE_FILE_NO_FOUND.equals(appEx.getMsgCode())) {
        throw appEx;
      }
    }
  }

  protected void validateUpdate(AbstractBaseObject obj) throws ApplicationException {
    RuleBaseObject ruleObject = (RuleBaseObject) obj;
    RuleBaseObject object = this.getRuleBaseObjectByRuleName(this.RULE_FILE_NAME, ruleObject.getRuleName());
    if (!Utility.isEmpty(object) && !ruleObject.getRuleID().equals(object.getRuleID())) {
      throw new ApplicationException(RuleErrorConstant.RULE_DUPLICATE_RULE_NAME);
    }
  }

  protected void validateDelete(AbstractBaseObject obj) throws ApplicationException {
  }

  /**
   * insert a RuleBaseObject
   * @param obj a Abstract Base Object
   * @return AbstractBaseObject
   */
  protected synchronized AbstractBaseObject insert(AbstractBaseObject obj) throws ApplicationException {
    Integer ruleID = this.getNextPrimaryID();
    RuleBaseObject ruleObj = (RuleBaseObject) obj;
    ruleObj.setID(ruleID);
    ruleObj.setRuleID(String.valueOf(ruleID.intValue()));

    ruleObj.setCreatorID(this.getSessionContainer().getUserRecordID());
    ruleObj.setUpdaterID(this.getSessionContainer().getUserRecordID());

    log.debug("Rule ID is " + ruleID);
    return this.insertRuleBaseObject(this.RULE_FILE_NAME, ruleObj);
  }

  /**
   * update a RuleBaseObject
   * @param obj a Abstract Base Object
   * @return AbstractBaseObject
   */
  protected synchronized AbstractBaseObject update(AbstractBaseObject obj) throws ApplicationException {
    return this.updateRuleBaseObject(this.RULE_FILE_NAME, (RuleBaseObject) obj);
  }

  /**
   * delete a RuleBaseObject
   * @param obj a Abstract Base Object
   * @return AbstractBaseObject
   */
  protected synchronized AbstractBaseObject delete(AbstractBaseObject obj) throws ApplicationException {
    return this.deleteRuleBaseObject(this.RULE_FILE_NAME, (RuleBaseObject) obj);
  }

  protected synchronized void auditTrail(String opMode, AbstractBaseObject obj) throws ApplicationException {
  }

  /**
   * delete a tatch rules from the Knowledge Base file
   * @param idAry the rule ID array
   */
  public synchronized void deleteList(String[] idAry) throws ApplicationException {
    for (int i = 0; i < idAry.length; i++) {
      this.removeRuleByRuleID(RULE_FILE_NAME, new Integer(idAry[i]));
    }
  }

  public synchronized AbstractBaseObject deleteObject(AbstractBaseObject obj) throws ApplicationException {
    this.validateDelete(obj);
    return this.deleteRuleBaseObject(this.RULE_FILE_NAME, (RuleBaseObject) obj);
  }

  //############################################################################################

  /**
   * get the rule from KnowledgeBase file by the rule ID
   * @param kbFile  File - KnowledgeBase file
   * @param ruleID  Integer - the rule ID
   * @return rule   Rule - org.mandarax.kernel.Rule
   * @throws ApplicationException
   * @see RuleOperationConstant#RULE_ID
   */
  public Rule getRuleByRuleID(File kbFile, Integer ruleID) throws ApplicationException {
    String ruleIDStr = ruleID.toString();
    KnowledgeBase kb = null;
    kb = this.importKnowledgeBase(kbFile);

    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleIDStr.equals(cs.getProperty(RuleOperationConstant.RULE_ID).toString())) {
          return (Rule) cs;
        }
      }
    }
    return null;
  }

  /**
   * get RuleBaseObject by rule ID
   * @param kbFile  the KnowledgeBase File
   * @param ruleID  the rule ID
   * @return RuleBaesObject
   * @throws ApplicationException
   */
  public RuleBaseObject getRuleBaseObjectByRuleID(File kbFile, Integer ruleID) throws ApplicationException {
    RuleMemberFactory factory = new RuleMemberFactory();
    Rule rule = this.getRuleByRuleID(kbFile, ruleID);
    return factory.getRuleData(rule);
  }

  /**
   * get rule base object by rule seq no
   * @param kbFile
   * @param ruleSeqNo
   * @return RuleBaseObject
   * @throws ApplicationException
   */
  public RuleBaseObject getRuleBaseObjectByRuleSeqNo(File kbFile, String ruleSeqNo) throws ApplicationException {
    RuleMemberFactory factory = new RuleMemberFactory();
    Rule rule = this.getRuleByRuleSeqNo(kbFile, ruleSeqNo);
    return factory.getRuleData(rule);
  }

  /**
   * get rule by rule name
   * @param kbFile  the KnowledgeBase file
   * @param ruleName  the rule name
   * @return Rule
   * @throws ApplicationException
   */
  public Rule getRuleByRuleName(File kbFile, String ruleName) throws ApplicationException {
    KnowledgeBase kb = null;
    kb = this.importKnowledgeBase(kbFile);

    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_NAME))) {
        if (ruleName.equalsIgnoreCase(cs.getProperty(RuleOperationConstant.RULE_NAME).toString())) {
          return (Rule) cs;
        }
      }
    }
    return null;
  }

  /**
   * get RuleBaseObject by rule name 
   * @param kbFile   the KnowledgeBase File
   * @param ruleName the rule name
   * @return RuleBaseObject
   * @throws ApplicationException
   */
  public RuleBaseObject getRuleBaseObjectByRuleName(File kbFile, String ruleName) throws ApplicationException {
    RuleMemberFactory factory = new RuleMemberFactory();
    Rule rule = this.getRuleByRuleName(kbFile, ruleName);
    return factory.getRuleData(rule);
  }

  /**
   * get RuleBaseObject by rule name 
   * @param kbFileName	  the KnowledgeBase File Name
   * @param ruleName      the rule name
   * @return RuleBaseObject
   * @throws ApplicationException
   */
  public RuleBaseObject getRuleBaseObjectByRuleName(String kbFileName, String ruleName) throws ApplicationException {
    RuleMemberFactory factory = new RuleMemberFactory();
    File kbFile = new File(this.getKBFilePath() + "/" + kbFileName);
    Rule rule = this.getRuleByRuleName(kbFile, ruleName);

    return factory.getRuleData(rule);
  }

  /**
   * get RuleBaseObject by rule ID
   * @param kbFileName the KnowledgeBase File Name
   * @param ruleID     the Rule ID
   * @return RuleBaseObject
   * @throws ApplicationException
   */
  public RuleBaseObject getRuleBaseObjectByRuleID(String kbFileName, Integer ruleID) throws ApplicationException {
    File kbFile = new File(this.getKBFilePath() + "/" + kbFileName);
    return this.getRuleBaseObjectByRuleID(kbFile, ruleID);
  }

  /**
   * remove a rule from KnowledgeBase file by the rule ID
   * @param kbFile  KnowledgeBase File
   * @param ruleID  The Rule ID
   * @return Rule 
   * @throws ApplicationException
   * @see importKnowledgeBase
   * @see exportKnowledgeBase
   * @see RuleOperationConstant#RULE_ID
   */
  public Rule removeRuleByRuleID(File kbFile, Integer ruleID) throws ApplicationException {
    String ruleIDStr = ruleID.toString();
    KnowledgeBase kb = null;
    kb = this.importKnowledgeBase(kbFile);

    Rule rule = null;

    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleIDStr.equals(cs.getProperty(RuleOperationConstant.RULE_ID).toString())) {
          rule = (Rule) cs;
          kb.remove(cs);
          break;
        }
      }
    }
    kb = this.resetRuleSeqNo(kb);
    this.exportKnowledgeBase(kb, kbFile);
    return rule;
  }

  /**
   * remove a rule from KnowledgeBase file by the rule ID
   * @param kbFile  KnowledgeBase File
   * @param ruleID  The Rule ID
   * @return Rule 
   * @throws ApplicationException
   * @see importKnowledgeBase
   * @see exportKnowledgeBase
   * @see RuleOperationConstant#RULE_ID
   */
  public Rule removenewRuleByRuleID(KnowledgeBase kb, Integer ruleID) throws ApplicationException {
    String ruleIDStr = ruleID.toString();
    //    KnowledgeBase kb = null;        
    //    kb = this.importKnowledgeBase(kbFile);

    Rule rule = null;

    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleIDStr.equals(cs.getProperty(RuleOperationConstant.RULE_ID).toString())) {
          rule = (Rule) cs;
          kb.remove(cs);
          break;
        }
      }
    }
    kb = this.resetRuleSeqNo(kb);
    //    this.exportKnowledgeBase(kb, kbFile);
    return rule;
  }

  /**
   * 
   * @param kbFileName
   * @param ruleID
   * @throws ApplicationException
   */
  public void removeRuleByRuleID(String kbFileName, Integer ruleID) throws ApplicationException {
    File kbFile = new File(this.getKBFilePath() + "/" + kbFileName);
    this.removeRuleByRuleID(kbFile, ruleID);
  }

  /**
   * add a rule to the KnowledgeBase file.
   * @param kbFile  KnowledgeBase
   * @param rule    Rule
   * @throws ApplicationException
   */
  public void addRuleToKbFile(File kbFile, Rule rule) throws ApplicationException {
    KnowledgeBase kb = null;
    kb = this.importKnowledgeBase(kbFile);
    List clauseSetList = kb.getClauseSets();
    kb.add(rule);

    this.exportKnowledgeBase(kb, kbFile);
  }

  /**
   * update a rule in KnowledgeBase file
   * @param kbFile KnowledgeBase file
   * @param rule   Rule
   * @throws ApplicationException
   * @see RuleOperationConstant#RULE_ID
   */
  public void updateRule(File kbFile, Rule rule) throws ApplicationException {
    KnowledgeBase kb = null;
    kb = this.importKnowledgeBase(kbFile);

    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (rule.getProperty(RuleOperationConstant.RULE_ID).equals(cs.getProperty(RuleOperationConstant.RULE_ID))) {
          kb.remove(cs);
          break;
        }
      }
    }
    kb.add(rule);
    this.exportKnowledgeBase(kb, kbFile);
  }

  /**
   * get the org.mandarax.zkb.ZKBDriver instance by the system parameter "rules.kb_driver_class"
   * if occur a error, use the org.mandarax.zkb.framework.ZKBDriver_2_0 instance.
   * @see org.mandarax.zkb.framework.ZKBDriver_2_0
   * @return org.mandarax.zkb.ZKBDriver 
   */
  public org.mandarax.zkb.ZKBDriver getZKBDriverInstance() {
    //		try {
    String driverClass = SystemParameterFactory.getSystemParameter(SystemParameterConstant.RULES_KB_DRIVER_CLASS);
    try {
      return (org.mandarax.zkb.ZKBDriver) Class.forName(driverClass).newInstance();
    } catch (ClassNotFoundException e) {
      return new ZKBDriver_2_0();
    } catch (InstantiationException e) {
      return new ZKBDriver_2_0();
    } catch (IllegalAccessException e) {
      return new ZKBDriver_2_0();
    }
    //		} catch (Exception e){
    //			return new ZKBDriver_2_0();
    //		}
  }

  /**
   * export a KnowledgeBase to a file
   * @param kb       KnowledgeBase
   * @param kbFile   File
   * @throws ApplicationException
   */
  public void exportKnowledgeBase(KnowledgeBase kb, File kbFile) throws ApplicationException {
    ZKBManager zkbManager = new ZKBManager();
    zkbManager.setDriver(this.getZKBDriverInstance());
    zkbManager.setOps(new XMLSerializationReadOPS());

    try {
      zkbManager.exportKnowledgeBase(kbFile, kb);
    } catch (ZKBException e) {
      log.debug("ZKB Import Error");
      throw new ApplicationException("ZKB Export Error", e);
    }
  }

  /**
   * import a KnowledgeBase from a file
   * @param kbFile  KnowledgeBase
   * @return KnowledgeBase
   * @throws ApplicationException
   */
  public KnowledgeBase importKnowledgeBase(File kbFile) throws ApplicationException {
    KnowledgeBase kb = null;
    ZKBManager zkbManager = new ZKBManager();
    zkbManager.setDriver(this.getZKBDriverInstance());
    zkbManager.setOps(new XMLSerializationReadOPS());

    if (!kbFile.exists()) {
      log.debug("KB File is " + kbFile.getAbsolutePath() + ", the file not found.");
      throw new ApplicationException(RuleErrorConstant.RULE_RULE_FILE_NO_FOUND);
    }

    log.debug("KB File is " + kbFile.getAbsolutePath());
    try {
      kb = zkbManager.importKnowledgeBase(kbFile);
    } catch (ZKBException e) {
      log.debug("ZKB Import Error");
      throw new ApplicationException("ZKB Import Error", e);
    }
    return kb;
  }

  /**
   * filter KnowledgeBase by a query
   * @param kb     KnowledgeBase
   * @param query  Query
   * @return ResultSet 
   * @throws ApplicationException
   */
  public ResultSet filterKbByQuery(KnowledgeBase kb, Query query) throws ApplicationException {
    ResolutionInferenceEngine4 ie = new ResolutionInferenceEngine4();
    ResultSet resultSet = null;
    try {
      resultSet = ie.query(query, kb, ie.ALL, ie.BUBBLE_EXCEPTIONS);
    } catch (InferenceException e) {
      log.debug("Inference Engine query error");
      throw new ApplicationException("Inference Engine query error", e);
    }
    return resultSet;
  }

  /**
   * filter KnowledgeBase by a query, get the KnowledgeBase from a file.
   * @param kbFile  KnowledgeBase File
   * @param query   Query
   * @return ResultSet
   * @throws ApplicationException
   */
  public ResultSet filterKbByQuery(File kbFile, Query query) throws ApplicationException {
    KnowledgeBase kb = this.importKnowledgeBase(kbFile);
    ResolutionInferenceEngine4 ie = new ResolutionInferenceEngine4();
    ResultSet resultSet = null;
    try {
      resultSet = ie.query(query, kb, ie.ALL, ie.BUBBLE_EXCEPTIONS);
    } catch (InferenceException e) {
      log.debug("Inference Engine query error");
      throw new ApplicationException("Inference Engine query error", e);
    }
    return resultSet;
  }

  /**
   * check if has the rule ID in the KnowledgeBase file.
   * @param kbFile  the KnowledgeBase File
   * @param ruleID  the Rule ID
   * @return boolean
   * @throws ApplicationException
   * @see RuleOperationConstant#RULE_ID
   */
  public boolean hasRuleID(File kbFile, Integer ruleID) throws ApplicationException {
    KnowledgeBase kb = this.importKnowledgeBase(kbFile);
    return this.hasRuleID(kb, ruleID);
  }

  /**
   * check if has the rule ID in the KnowledgeBase
   * @param kb    the KnowledgeBase
   * @param ruleID  the Rule ID
   * @return boolean
   * @throws ApplicationException
   * @see RuleOperationConstant#RULE_ID
   */
  public boolean hasRuleID(KnowledgeBase kb, Integer ruleID) {
    boolean hasRule = false;
    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleID.toString().equals(cs.getProperty(RuleOperationConstant.RULE_ID).toString())) {
          hasRule = true;
          break;
        }
      }
    }
    return hasRule;
  }

  /**
   * check if has rule name in the KnowledgeBase file
   * @param kbFile  the KnowledgeBase
   * @param ruleName  the rule name
   * @return boolean
   * @throws ApplicationException
   * @see RuleOperationConstant#RULE_NAME
   */
  public boolean hasRuleID(File kbFile, String ruleName) throws ApplicationException {
    KnowledgeBase kb = this.importKnowledgeBase(kbFile);
    return this.hasRuleName(kb, ruleName);
  }

  /**
   * check if has rule name in the KnowledgeBase
   * @param kb  the KnowledgeBase
   * @param ruleName the rule name
   * @return boolean
   * @see RuleOperationConstant#RULE_NAME
   */
  public boolean hasRuleName(KnowledgeBase kb, String ruleName) {
    boolean hasRule = false;
    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_NAME))) {
        if (ruleName.equals(cs.getProperty(RuleOperationConstant.RULE_NAME).toString())) {
          hasRule = true;
          break;
        }
      }
    }
    return hasRule;
  }

  /**
   * get the KnowledgeBase file path
   * @return Stirng
   */
  public String getKBFilePath() {
    String path = SystemParameterFactory.getSystemParameter(SystemParameterConstant.RULES_KB_FILE_PATH);
    return path;
  }

  /**
   * unite with two KnowledgeBase
   * @param kb1 a KnowledgeBase
   * @param kb2 another KnowledgeBase
   * @return KnoqledgetBase
   */
  public KnowledgeBase unionKnowledgeBase(KnowledgeBase kb1, KnowledgeBase kb2) {
    for (int i = 0; i < kb2.getClauseSets().size(); i++) {
      kb1.add((ClauseSet) kb2.getClauseSets().get(i));
    }
    return kb1;
  }

  /**
   * unite with two KnowledgeBase that get it from tow KnowledgeBase file
   * @param kbFile1 a KnowledgeBase file
   * @param kbFile2 another KnowledgeBase file
   * @return KnowledgeBase
   * @throws ApplicationException
   */
  public KnowledgeBase unionKnowledgeBase(File kbFile1, File kbFile2) throws ApplicationException {
    KnowledgeBase kb1 = this.importKnowledgeBase(kbFile1);
    KnowledgeBase kb2 = this.importKnowledgeBase(kbFile2);

    return this.unionKnowledgeBase(kb1, kb2);
  }

  /**
   * get RuleBaseObject List
   * @param kb a KnowledgeBase
   * @param searchForm  the Abstract Search Form
   * @return list
   * @throws ApplicationException
   */
  public List getRuleList(KnowledgeBase kb, AbstractSearchForm searchForm) throws ApplicationException {
    RuleMemberFactory factory = new RuleMemberFactory();
    List result = new ArrayList();
    List clauseSet = kb.getClauseSets();
    List tmpClauseSet = new ArrayList();

    int totalNumOfRule = 0;

    //filter the clause set.
    if (!Utility.isEmpty(searchForm) && searchForm.isSearchable()) {
      tmpClauseSet = this.filterClauseSet(clauseSet, searchForm.getBasicSearchField(), searchForm.getBasicSearchType(), searchForm.getBasicSearchKeyword());
    }
    
    log.debug("fitlter clause set finish!");

    if (!Utility.isEmpty(clauseSet)) {
      totalNumOfRule = clauseSet.size();
    }

    //get all rule list
    if (Utility.isEmpty(searchForm)) {
      log.debug("get all rule list");
      for (int i = 0; i < clauseSet.size(); i++) {
        RuleBaseObject ruleBaseObject = factory.getRuleData((Rule) clauseSet.get(i));
        if(tmpClauseSet.contains(clauseSet.get(i))){
          ruleBaseObject.setIsHighLight(true);
        }
        result.add(ruleBaseObject);
      }

      //order by seq no.
      result = BeansSorter.sortAscending(result, RuleOperationConstant.RULE_SEQ_NO);

      //get a page rule	
    } else {
      String sortOrder = searchForm.getSortOrder();
      String sortKey = searchForm.getSortAttribute();

      log.debug("Sort Order | Sort Key : " + sortOrder + " | " + sortKey);

      List tmpList = new ArrayList();
      for (int i = 0; i < clauseSet.size(); i++) {
        RuleBaseObject ruleBaseObject = factory.getRuleData((Rule) clauseSet.get(i));
        if(tmpClauseSet.contains(clauseSet.get(i))){
          ruleBaseObject.setIsHighLight(true);
        }
        tmpList.add(ruleBaseObject);
        //tmpList.add(factory.getRuleData((Rule) clauseSet.get(i)));
      }

      //Sort by the sort key
      tmpList = BeansSorter.sort(tmpList, sortKey, "ASC".equals(sortOrder) ? 0 : 1);
      log.debug("Sort after Result size :" + tmpList.size());

      log.debug("get a page rule.");
      int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
      int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
      log.debug("startOffset | pageSize : " + startOffset + ":" + pageSize);

      for (int i = startOffset - 1; i < (pageSize + startOffset - 1) && i < tmpList.size(); i++) {
        result.add(factory.setRowNumRecordCount((RuleBaseObject) (tmpList.get(i)), i + 1, totalNumOfRule));
      }
    }

    return result;
  }

  /**
   * get RuleBaseObject List
   * @param file a KnowledgeBase file
   * @param searchForm  the AbstractSearch Form
   * @return list
   * @throws ApplicationException
   */
  public List getRuleList(File file, AbstractSearchForm searchForm) throws ApplicationException {
    KnowledgeBase kb = this.importKnowledgeBase(file);
    return this.getRuleList(kb, searchForm);
  }

  /**
   * get RuleBaseObject List by the fileName,
   * the path is got form the getKBFilePath.
   * @param file a KnowledgeBase file name
   * @param searchForm  the AbstractSearch Form	 * 
   * @return list
   * @throws ApplicationException
   * @see getKBFilePath()
   */
  public List getRuleList(String fileName, AbstractSearchForm searchForm) throws ApplicationException {
    File file = new File(this.getKBFilePath() + "/" + fileName);
    log.debug("KB File:  " + this.getKBFilePath() + "/" + fileName);
    if (!file.exists()) {
      log.debug("No found the KnowledgeBase file, No Record Found!");
      return new ArrayList();
    }

    KnowledgeBase kb = this.importKnowledgeBase(file);
    return this.getRuleList(kb, searchForm);
  }

  /**
   * get all rule from a KnowledgeBase file
   * @param fileName  a KnowledgeBase file name
   * @return list
   * @throws ApplicationException
   */
  public List getAllRuleList(String fileName) throws ApplicationException {
    return this.getRuleList(fileName, null);
  }

  /**
   * get all rule from a KnowledgeBase file
   * @param kbFile  a KnowledgeBase file
   * @return list
   * @throws ApplicationException
   */
  public List getAllRuleList(File kbFile) throws ApplicationException {
    return this.getRuleList(kbFile, null);
  }

  /**
   * insert RuleBaseObject 
   * @param kb a KnowledgeBase
   * @param kbFile a KnowledgeBase file
   * @param ruleObj a RuleBaseObject
   * @return RuleBaseObject
   * @throws ApplicationException
   */
  public RuleBaseObject insertRuleBaseObject(KnowledgeBase kb, File kbFile, RuleBaseObject ruleObj) throws ApplicationException {
    RuleMemberFactory factory = new RuleMemberFactory();
    log.debug("ruleObj ruleID : ID :" + ruleObj.getRuleID() + ":" + ruleObj.getID());

    if (Utility.isEmpty(ruleObj.getRuleSeqNo())) {
      ruleObj.setRuleSeqNo(String.valueOf(this.getNextSeq(kb)));
    }
    ruleObj.setUpdateCount(new Integer(0));
    Rule rule = factory.parseRule(ruleObj);
    kb = shiftRuleSeqNo(kb, rule);

    this.commitKnowledgeBase(kb, kbFile);
    return factory.getRuleData(rule);
  }

  /**
   * insert RuleBaseObject
   * @param kbFileName  a KnowledgeBase file name
   * @param ruleObj  a RuleBaseObject
   * @return RuleBaseObject
   * @throws ApplicationException
   */
  public RuleBaseObject insertRuleBaseObject(String kbFileName, RuleBaseObject ruleObj) throws ApplicationException {
    File kbFile = new File(this.getKBFilePath() + "/" + kbFileName);
    KnowledgeBase kb = null;

    //if the kbFile exist, append the rule
    if (kbFile.exists()) {
      log.debug("KB File Exist, import the KB.");
      kb = this.importKnowledgeBase(kbFile);

      //if the kbFile not exist, create the kbFile first
    } else {
      log.debug("KB File not exit, create the kbFile first.");
      kb = new AdvancedKnowledgeBase();
      this.exportKnowledgeBase(kb, kbFile);
    }

    return this.insertRuleBaseObject(kb, kbFile, ruleObj);
  }

  /**
   * update a RuleBaseObject
   * @param kbFileName a KnowledgeBase file name
   * @param ruleObj a RuleBaseObject
   * @return RuleBaseObject
   * @throws ApplicationException
   */
  public RuleBaseObject updateRuleBaseObject(String kbFileName, RuleBaseObject ruleObj) throws ApplicationException {

    File kbFile = new File(this.getKBFilePath() + "/" + kbFileName);
    KnowledgeBase kb = this.importKnowledgeBase(kbFile);
    RuleMemberFactory factory = new RuleMemberFactory();

    if (Utility.isEmpty(ruleObj.getRuleSeqNo())) {
      ruleObj.setRuleSeqNo(String.valueOf(this.getNextSeq(kb)));
    }
    ruleObj.setUpdateCount(new Integer(1));
    Rule rule = factory.parseRule(ruleObj);
    //Remove the old Rule first
    Rule oldRule = this.removeRuleByRuleID(kbFile, new Integer(ruleObj.getRuleID()));
    //Rule oldRule=rule;

    if (!Utility.isEmpty(oldRule)) {
      rule.setProperty(RuleOperationConstant.RULE_CREATOR_ID, oldRule.getProperty(RuleOperationConstant.RULE_CREATOR_ID));
      rule.setProperty(RuleOperationConstant.RULE_CREATE_DATE, oldRule.getProperty(RuleOperationConstant.RULE_CREATE_DATE));
      rule.setProperty(RuleOperationConstant.RULE_UPDATER_ID, sessionContainer.getUserRecordID().toString());
      rule.setProperty(RuleOperationConstant.RULE_UPDATE_DATE, Utility.getCurrentTimestamp().toString());

      int count = TextUtility.parseInteger(oldRule.getProperty(RuleOperationConstant.RULE_UPDATE_COUNT));
      rule.setProperty(RuleOperationConstant.RULE_UPDATE_COUNT, String.valueOf(++count));
    }

    //Add the new Rule second
    kb = this.importKnowledgeBase(kbFile);

    kb = shiftRuleSeqNo(kb, rule);
    this.commitKnowledgeBase(kb, kbFile);

    return factory.getRuleData(rule);
  }

  /**
   * delete a RuleBaseObject
   * @param kbFileName a KnowledgeBase file name
   * @param ruleObj a RuleBaseObject
   * @return RuleBaseObject
   * @throws ApplicationException
   */
  public RuleBaseObject deleteRuleBaseObject(String kbFileName, RuleBaseObject ruleObj) throws ApplicationException {
    File kbFile = new File(this.getKBFilePath() + "/" + kbFileName);
    KnowledgeBase kb = this.importKnowledgeBase(kbFile);

    RuleMemberFactory factory = new RuleMemberFactory();
    //  	Rule rule = factory.parseRule(ruleObj);  

    //Remove the Rule first
    this.removeRuleByRuleID(kbFile, new Integer(ruleObj.getRuleID()));

    //		return factory.getRuleData(rule);
    return ruleObj;
  }

  /**
   * filter the Clause Set 
   * @param clauseSet a ClasuseSet 
   * @param filterField a filter field
   * @param filterType a filter type
   * @param filterKeyword a filter keyword
   * @return list
   */
  public List filterClauseSet(List clauseSet, String filterField, String filterType, String filterKeyword) {
    log.debug("Filter clauseSet by filterField | filterType | filterKeyword: " + filterField + "|" + filterType + "|" + filterKeyword);
    List result = new ArrayList();
    for (int i = 0; i < clauseSet.size(); i++) {
      Rule rule = (Rule) clauseSet.get(i);
      String item = rule.getProperty(filterField).toUpperCase();

      log.debug("Teh item is " + item);

      if (!Utility.isEmpty(item)) {
        //Contains
        if (RuleOperationConstant.STRING_CONTAINS.equals(filterType)) {
          if (item.indexOf(filterKeyword.toUpperCase()) > -1) {
            result.add(rule);
          }

          //Start With	
        } else if (RuleOperationConstant.STRING_START_WITH.equals(filterType)) {
          if (item.startsWith(filterKeyword.toUpperCase())) {
            result.add(rule);
          }

          //Equals	
        } else if (RuleOperationConstant.STRING_EQUALS.equals(filterType)) {
          if (item.equalsIgnoreCase(filterKeyword.toUpperCase())) {
            result.add(rule);
          }

          //Not Equals	
        } else if (RuleOperationConstant.STRING_NOT_EQUALS.equals(filterType)) {
          if (!item.equalsIgnoreCase(filterKeyword.toUpperCase())) {
            result.add(rule);
          }
        }

      }

    }

    return result;
  }

  /**
   * commit a KnowledgeBase to the KB file
   * @param kb a KnowledgeBase
   * @param kbFile a KnowledgeBase file
   * @throws ApplicationException
   */
  public void commitKnowledgeBase(KnowledgeBase kb, File kbFile) throws ApplicationException {
    this.exportKnowledgeBase(kb, kbFile);
  }

  /**
   * get Next rule Seq No.
   * @param kb a KnowledgeBase
   * @return int
   */
  private int getNextSeq(KnowledgeBase kb) {
    if (!Utility.isEmpty(kb.getClauseSets())) {
      return kb.getClauseSets().size() + 1;
    }
    return 1;
  }

  /**
   * shift the rule seq no.
   * @param kb a KnowledgeBase
   * @param currentRule a rule
   * @return KnowledgeBase
   */
  private KnowledgeBase shiftRuleSeqNo(KnowledgeBase kb, Rule currentRule) {
    KnowledgeBase resultKB = new AdvancedKnowledgeBase();
    List clauseList = kb.getClauseSets();
    int currentSeqNo = Integer.parseInt(currentRule.getProperty(RuleOperationConstant.RULE_SEQ_NO));

    for (int i = 0; i < clauseList.size(); i++) {
      Rule rule = (Rule) clauseList.get(i);
      int tmpSeqNo = Integer.parseInt(rule.getProperty(RuleOperationConstant.RULE_SEQ_NO));

      if (tmpSeqNo < currentSeqNo) {
        resultKB.add(rule);

      } else {
        rule.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer(tmpSeqNo + 1)));
        resultKB.add(rule);
      }
    }
    resultKB.add(currentRule);
    return trimSeqNo(resultKB);
  }

  /**
   * trim seq no
   * @param kb a KnowledgeBase
   * @return KnowledgeBase
   */
  private KnowledgeBase trimSeqNo(KnowledgeBase kb) {
    KnowledgeBase resultKB = new AdvancedKnowledgeBase();
    RuleMemberFactory factory = new RuleMemberFactory();

    List clauseList = kb.getClauseSets();
    List ruleObjList = new ArrayList();

    for (int i = 0; i < clauseList.size(); i++) {
      ruleObjList.add(factory.getRuleData((Rule) (clauseList.get(i))));
    }

    ruleObjList = BeansSorter.sortAscending(ruleObjList, RuleOperationConstant.RULE_SEQ_NO);

    for (int i = 0; i < ruleObjList.size(); i++) {
      RuleBaseObject ruleObj = (RuleBaseObject) ruleObjList.get(i);
      Rule rule = ruleObj.getRuleSource();
      rule.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer(i + 1)));
      resultKB.add(rule);
    }

    return resultKB;
  }

  /**
   * reset the rule seq no. after deleted a rule
   * @param kb a KnowledgeBase
   * @return KnowledgeBase
   */
  private KnowledgeBase resetRuleSeqNo(KnowledgeBase kb) {
    KnowledgeBase resultKB = new AdvancedKnowledgeBase();

    kb = trimSeqNo(kb);
    List clauseList = kb.getClauseSets();

    for (int i = 0; i < clauseList.size(); i++) {
      Rule rule = (Rule) clauseList.get(i);
      rule.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer(i + 1)));
      resultKB.add(rule);
    }

    return resultKB;
  }

  public Rule getRuleByRuleSeqNo(File kbFile, String ruleSeqNo) throws ApplicationException {
    //String ruleIDStr = ruleID.toString();
    KnowledgeBase kb = null;
    kb = this.importKnowledgeBase(kbFile);

    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_SEQ_NO))) {
        if (Integer.parseInt(ruleSeqNo) == Integer.parseInt(cs.getProperty(RuleOperationConstant.RULE_SEQ_NO).toString())) {
          return (Rule) cs;
        }
      }
    }
    return null;
  }

  public synchronized AbstractBaseObject getObjectByRuleSeqNo(String ruleSeqNo) throws ApplicationException {
    RuleMemberFactory factory = new RuleMemberFactory();
    File kbFile = new File(this.getKBFilePath() + "/" + RULE_FILE_NAME);

    return this.getRuleBaseObjectByRuleSeqNo(kbFile, ruleSeqNo);
  }

  public synchronized AbstractBaseObject updateNewObject(AbstractBaseObject obj) throws ApplicationException {

    return this.updateNewRuleBaseObject(this.RULE_FILE_NAME, (RuleBaseObject) obj);
  }

  public Rule removeNewRuleByRuleID(KnowledgeBase kb, Integer ruleID) throws ApplicationException {
    String ruleIDStr = ruleID.toString();

    Rule rule = null;

    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleIDStr.equals(cs.getProperty(RuleOperationConstant.RULE_ID).toString())) {
          rule = (Rule) cs;
          kb.remove(cs);
          break;
        }
      }
    }
    kb = this.resetRuleSeqNo(kb);
    //    this.exportKnowledgeBase(kb, kbFile);
    return rule;
  }

  /**
   * update a ruleBaeObject
   * @param kbFileName
   * @param ruleObj
   * @return
   * @throws ApplicationException
   */
  public RuleBaseObject updateNewRuleBaseObject(String kbFileName, RuleBaseObject ruleObj) throws ApplicationException {

    File kbFile = new File(this.getKBFilePath() + "/" + kbFileName);

    KnowledgeBase kb = this.importKnowledgeBase(kbFile);

    RuleMemberFactory factory = new RuleMemberFactory();

    if (Utility.isEmpty(ruleObj.getRuleSeqNo())) {
      ruleObj.setRuleSeqNo(String.valueOf(this.getNextSeq(kb)));
    }
    ruleObj.setUpdateCount(new Integer(1));
    Rule rule = factory.parseRule(ruleObj);
    //Remove the old Rule first
    Rule oldRule = this.removeNewRuleByRuleID(kb, new Integer(ruleObj.getRuleID()));
    if (!Utility.isEmpty(oldRule)) {
      rule.setProperty(RuleOperationConstant.RULE_CREATOR_ID, oldRule.getProperty(RuleOperationConstant.RULE_CREATOR_ID));
      rule.setProperty(RuleOperationConstant.RULE_CREATE_DATE, oldRule.getProperty(RuleOperationConstant.RULE_CREATE_DATE));
      rule.setProperty(RuleOperationConstant.RULE_UPDATER_ID, sessionContainer.getUserRecordID().toString());
      rule.setProperty(RuleOperationConstant.RULE_UPDATE_DATE, Utility.getCurrentTimestamp().toString());

      int count = TextUtility.parseInteger(oldRule.getProperty(RuleOperationConstant.RULE_UPDATE_COUNT));
      rule.setProperty(RuleOperationConstant.RULE_UPDATE_COUNT, String.valueOf(++count));
    }

    //Add the new Rule second
    //kb = this.importKnowledgeBase(kbFile); 

    kb = shiftRuleSeqNo(kb, rule);

    //    Rule rule=getUpdateRule(ruleObj, kb, factory);

    this.commitKnowledgeBase(kb, kbFile);

    return factory.getRuleData(rule);
  }

  public void updateBatchRuleBaseObject(List ruleList, boolean enabled) throws ApplicationException {
    File kbFile = new File(this.getKBFilePath() + "/" + this.RULE_FILE_NAME);
    KnowledgeBase kb = this.importKnowledgeBase(kbFile);

    List clauseSetList = kb.getClauseSets();
    for (Iterator iter = ruleList.iterator(); iter.hasNext();) {
      Integer element = (Integer) iter.next();

      for (int i = 0; i<clauseSetList.size(); i++) {
        ClauseSet cs = (ClauseSet) clauseSetList.get(i);
        if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
          if (element.intValue() == TextUtility.parseInteger((cs.getProperty(RuleOperationConstant.RULE_ID).toString()))) {
            if (enabled) {
            cs.setProperty(RuleOperationConstant.RULE_STATUS_ENABLED, GlobalConstant.TRUE);
            }else{
              cs.setProperty(RuleOperationConstant.RULE_STATUS_ENABLED, GlobalConstant.FALSE);
            }
          }

        }
      }
      }
    
    this.commitKnowledgeBase(kb, kbFile);

  }

  public synchronized void enableBatchObject(List ruleList, boolean enabled) {
    try {
      updateBatchRuleBaseObject(ruleList, enabled);
    } catch (ApplicationException e) {
      log.error("enableBatchObject Error "+e);
    }
  }

  public synchronized void upBatchObject(List ruleList, boolean moveUp) {
    try {
      moveUpBatchRuleBaseObject(ruleList, moveUp);
    } catch (ApplicationException e) {
      log.error("upBatchObject Error "+e);
    }
  }

  private void moveUpBatchRuleBaseObject(List ruleList, boolean moveUp) throws ApplicationException {
    File kbFile = new File(this.getKBFilePath() + "/" + this.RULE_FILE_NAME);
    KnowledgeBase kb = this.importKnowledgeBase(kbFile);

    if (moveUp) {
      for (Iterator iter = ruleList.iterator(); iter.hasNext();) {
        Integer element = (Integer)iter.next();
        moveUpRule(kb, element);
      }
    } else {
      for (int i = ruleList.size() - 1; i >= 0; i--) {
        Integer element = (Integer) ruleList.get(i);
        moveDownRule(kb, element);
      }
    }
    this.commitKnowledgeBase(kb, kbFile);
  }

  private RuleBaseObject getRuleBaseObjectByID(KnowledgeBase kb, Integer ruleID) {
    String ruleIDStr = ruleID.toString();
    RuleMemberFactory factory = new RuleMemberFactory();
    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleIDStr.equals(cs.getProperty(RuleOperationConstant.RULE_ID).toString())) {
          return factory.getRuleData((Rule) cs);
        }
      }
    }
    return null;
  }


  public RuleBaseObject getRuleByRuleSeqNo(KnowledgeBase kb, String ruleSeqNo) throws ApplicationException {
    //String ruleIDStr = ruleID.toString();
    RuleMemberFactory factory = new RuleMemberFactory();
    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_SEQ_NO))) {
        if (Integer.parseInt(ruleSeqNo) == Integer.parseInt(cs.getProperty(RuleOperationConstant.RULE_SEQ_NO).toString())) {
          return factory.getRuleData((Rule) cs);
        }
      }
    }
    return null;
  }

  public Rule removeORuleByRuleID(KnowledgeBase kb, Integer ruleID) throws ApplicationException {
    String ruleIDStr = ruleID.toString();
    //    KnowledgeBase kb = null;        
    //    kb = this.importKnowledgeBase(kbFile);

    Rule rule = null;

    List clauseSetList = kb.getClauseSets();
    for (int i = 0; i < clauseSetList.size(); i++) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleIDStr.equals(cs.getProperty(RuleOperationConstant.RULE_ID).toString())) {
          rule = (Rule) cs;
          kb.remove(cs);
          break;
        }
      }
    }

    //    this.exportKnowledgeBase(kb, kbFile);
    return rule;
  }

  private void moveDownRule(KnowledgeBase kb, Integer ruleID) throws ApplicationException {
    RuleBaseObject ruleObj = getRuleBaseObjectByID(kb, ruleID);
    int RuleSeq = (new Integer(ruleObj.getRuleSeqNo())).intValue();
    List clauseSetList = kb.getClauseSets();
    
    if (RuleSeq>=clauseSetList.size()){
      return;
    }
    RuleBaseObject nextRuleObj = getRuleByRuleSeqNo(kb, String.valueOf(RuleSeq + 1));
    int nextRuleID = (new Integer(nextRuleObj.getRuleID())).intValue();

    for (int i = clauseSetList.size() - 1; i >= 0; i--) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleID.intValue() == TextUtility.parseInteger((cs.getProperty(RuleOperationConstant.RULE_ID).toString()))) {
          cs.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer(RuleSeq + 1)));
        }
        if (nextRuleID == TextUtility.parseInteger((cs.getProperty(RuleOperationConstant.RULE_ID).toString()))) {
          cs.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer(RuleSeq)));
        }
      }
    }

  }
  
  private void moveUpRule(KnowledgeBase kb, Integer ruleID) throws ApplicationException {
    RuleBaseObject ruleObj = getRuleBaseObjectByID(kb, ruleID);
    int ruleSeq = (new Integer(ruleObj.getRuleSeqNo())).intValue();
    List clauseSetList = kb.getClauseSets();
    
    if (ruleSeq==1){
      return;
    }
    RuleBaseObject proRuleObj = getRuleByRuleSeqNo(kb, String.valueOf(ruleSeq -1 ));
    int proRuleID = (new Integer(proRuleObj.getRuleID())).intValue();

    for (int i = clauseSetList.size() - 1; i >= 0; i--) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (!Utility.isEmpty(cs.getProperty(RuleOperationConstant.RULE_ID))) {
        if (ruleID.intValue() == TextUtility.parseInteger((cs.getProperty(RuleOperationConstant.RULE_ID).toString()))) {
          cs.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer(ruleSeq - 1)));
        }
        if (proRuleID == TextUtility.parseInteger((cs.getProperty(RuleOperationConstant.RULE_ID).toString()))) {
          cs.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer(ruleSeq)));
        }
      }
    }

  }
  
  public void dragRuleBaseObject(Integer sourceID,Integer targetID) throws ApplicationException {
    File kbFile = new File(this.getKBFilePath() + "/" + this.RULE_FILE_NAME);
    KnowledgeBase kb = this.importKnowledgeBase(kbFile);

    DropMoveRule(kb, sourceID,targetID);
  
    this.commitKnowledgeBase(kb, kbFile);
  }
  
  private void DropMoveRule(KnowledgeBase kb, Integer sourceID,Integer targetID) throws ApplicationException {
    RuleBaseObject sourceRuleObj = getRuleBaseObjectByID(kb, sourceID);
    int sourceRuleSeq = (new Integer(sourceRuleObj.getRuleSeqNo())).intValue();
    List clauseSetList = kb.getClauseSets();
    
    if (sourceRuleSeq>clauseSetList.size()){
      return;
    }
    RuleBaseObject targetRuleObj = getRuleBaseObjectByID(kb, targetID);
    int targetRuleSeq = (new Integer(targetRuleObj.getRuleSeqNo())).intValue();

    String[] nextRuleID = null;
    String[] moveSeq = null;
    if(sourceRuleSeq>targetRuleSeq){
      int value = sourceRuleSeq - targetRuleSeq;
      nextRuleID = new String[value];
      moveSeq = new String[value];
      for(int i=0;i<value;i++){
        RuleBaseObject nextRuleObj = getRuleByRuleSeqNo(kb, String.valueOf(targetRuleSeq + i));
        nextRuleID[i] = nextRuleObj.getRuleID();
        moveSeq[i] = (new Integer(targetRuleSeq + i + 1)).toString();        
      }
      
    }else{
      int value = targetRuleSeq - sourceRuleSeq;
      nextRuleID = new String[value];
      moveSeq = new String[value];
      for(int i=0;i<value;i++){
        RuleBaseObject nextRuleObj = getRuleByRuleSeqNo(kb, String.valueOf(targetRuleSeq - i));
        nextRuleID[i] = nextRuleObj.getRuleID();
        moveSeq[i] = (new Integer(targetRuleSeq - i - 1)).toString();      
      }
    }
    
    
    for (int i = clauseSetList.size() - 1; i >= 0; i--) {
      ClauseSet cs = (ClauseSet) clauseSetList.get(i);
      if (sourceID.intValue() == TextUtility.parseInteger((cs.getProperty(RuleOperationConstant.RULE_ID).toString()))) {
        cs.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer(targetRuleSeq)));   
      }
      if(!Utility.isEmpty(nextRuleID)){
        for(int j=0;j<nextRuleID.length;j++){
          if(TextUtility.parseInteger(nextRuleID[j]) == TextUtility.parseInteger((cs.getProperty(RuleOperationConstant.RULE_ID).toString()))){
            cs.setProperty(RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, TextUtility.parseIntegerObj(moveSeq[j])));   
          }
        }
      }
    }
    

  }
    
}
